package com.lsq.lwf.common.sqlmap;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.transaction.Transaction;

import org.apache.commons.lang3.StringUtils;

import com.lsq.lwf.common.aspect.factory.LightAspectFactory;
import com.lsq.lwf.common.datasource.ConnectionDS;
import com.lsq.lwf.common.exception.LightException;
import com.lsq.lwf.common.sqlmap.intf.SqlMap;
import com.lsq.lwf.common.utils.ActualInterface;
import com.lsq.lwf.common.xmlparse.base.BaseXml;
import com.sun.org.apache.commons.beanutils.BeanUtils;

public class SqlMapSupport<T> extends BaseXml implements SqlMap<T> {

	private Connection con = ConnectionDS.getConnection();
	private PreparedStatement pstmt = null;
	private ResultSet rs = null;
	private ResultSetMetaData rsmd = null;
	
	
	@SuppressWarnings("rawtypes")
	public SqlMapSupport getSqlMapSupport (){
		SqlMapSupport ss= (SqlMapSupport) LightAspectFactory.getProxyObject(SqlMapSupport.class.getName());
		
		return ss;
	}
	
	@SuppressWarnings("unchecked")
	private Class<T> entity = ActualInterface.getInterfaceActualClass(
			getClass(), 0);
	private HashMap<String, String> sqlMap = sqlNamespaceMap.get("user-sql");

	public List<T> queryForList(String queryName, List<Object> params) {
		List<T> list = null;
		try {

			String sql = sqlMap.get(queryName);
			if (StringUtils.isNotBlank(sql)) {
				pstmt = con.prepareStatement(sql);
				setParams(params, pstmt);

				rs = pstmt.executeQuery();

				rsmd = rs.getMetaData();
				list = new ArrayList<T>();
				while (rs.next()) {
					T t = (T) entity.newInstance();
//					rsmd.get
					BeanUtils.populate(t, new HashMap());
					list.add(t);
				}

			} else {
				new LightException(queryName + " is not found!");
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

	public boolean insert(String insertName, List<Object> params) {

		String sql = this.sqlMap.get(insertName);
		int count = 0;
		if (StringUtils.isNotBlank(sql)) {
			try {
				
				con.setAutoCommit(false);
				pstmt = con.prepareStatement(sql);
				setParams(params, pstmt);
				count = pstmt.executeUpdate();
				
				con.commit();
			} catch (Exception e) {
				try {
					con.rollback();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
				
			}

		}

		return count == 0 ? false : true;
	}

	public boolean delete(String deleteName, List<Object> params) {

		String sql = this.sqlMap.get(deleteName);
		int count = 0;
		if (StringUtils.isNotBlank(sql)) {
			try {
				pstmt = con.prepareStatement(sql);
				setParams(params, pstmt);

				count = pstmt.executeUpdate();
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

		return count == 0 ? false : true;
	}

	public boolean update(String updateName, List<Object> params) {

		String sql = this.sqlMap.get(updateName);
		int count = 0;
		if (StringUtils.isNotBlank(sql)) {
			try {
				pstmt = con.prepareStatement(sql);

				setParams(params, pstmt);

				count = pstmt.executeUpdate();

			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return count == 0 ? false : true;
	}

	private boolean checkParams(List<Object> params) {
		if (params != null && !params.isEmpty()) {
			return true;
		}
		return false;
	}

	private void setParams(List<Object> params, PreparedStatement pstmt)
			throws Exception {
		if (checkParams(params)) {
			for (int i = 0; i < params.size(); i++) {
				Object obj = params.get(i);
				if (obj instanceof String) {
					pstmt.setString(i, (String) obj);
				} else if (obj instanceof Integer) {
					pstmt.setInt(i, (Integer) obj);
				} else if (obj instanceof Boolean) {
					pstmt.setBoolean(i, (Boolean) obj);
				}else if(obj instanceof Byte){
					pstmt.setByte(i, (Byte)obj);
				}else if(obj instanceof Long){
					pstmt.setLong(i, (Long)obj);
				}else if(obj instanceof Double){
					pstmt.setDouble(i, (Double)obj);
				}else if(obj instanceof Float){
					pstmt.setDouble(i, (Float)obj);
				}else if(obj instanceof Date){
					pstmt.setDate(i, (java.sql.Date)obj);
				}
			}
		}
	}

}
